package com.mql.onlinechatsystem.system.controller;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.mql.onlinechatsystem.system.entity.TbMessage;
import com.mql.onlinechatsystem.system.entity.TbMessagerelation;
import com.mql.onlinechatsystem.system.mapper.TbMessageMapper;
import com.mql.onlinechatsystem.system.mapper.TbMessagerelationMapper;
import com.mql.onlinechatsystem.system.vo.TbMessagerelationVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

/**
 * @ServerEndpoint 注解是一个类层次的注解，它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@Slf4j
@ServerEndpoint("/websocket/{userid}")
@Component// 指定websocket 连接的url
public class WebSocketService {
    /**
     * 用来存放每个客户端对应的MyWebSocket对象。
     **/
    private static CopyOnWriteArraySet<WebSocketService> webSocketSet = new CopyOnWriteArraySet<>();

    private static Map<String,Session> map = new HashMap<String, Session>();
    
    private static List<TbMessagerelation> tbMessagerelations=new ArrayList<>();
    private static TbMessagerelation tbMessagerelation=new TbMessagerelation();
    private static List<TbMessage> tbMessages=new ArrayList<>();
    private static TbMessage tbMessage=new TbMessage();
    
    private static TbMessagerelationVo tbMessagerelationVo=new TbMessagerelationVo();

    private static TbMessagerelationMapper tbMessagerelationMapper;
    @Autowired
    public void setTbMessagerelationMapper(TbMessagerelationMapper tbMessagerelationMapper){
        WebSocketService.tbMessagerelationMapper=tbMessagerelationMapper;
    }


//    private TbMessagerelationMapper tbMessagerelationMapper;
    private static TbMessageMapper tbMessageMapper;
    @Autowired
    public void setTbMessageMapper(TbMessageMapper tbMessageMapper){
        WebSocketService.tbMessageMapper=tbMessageMapper;
    }
//    private TbMessageMapper tbMessageMapper;

    private static StringRedisTemplate stringRedisTemplate;
    @Autowired
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate){
        WebSocketService.stringRedisTemplate=stringRedisTemplate;
    }
//    private StringRedisTemplate stringRedisTemplate;

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     **/
    private Session session;

    private String userid;

    @OnOpen
    public void onOpen(@PathParam("userid") String userid,Session session) {
        //,@PathVariable("userid") String userid
        this.session = session;
        this.userid=userid;
        map.put(userid, session);
        webSocketSet.add(this);
        System.out.println("有新连接加入:"+",当前在线人数为" + webSocketSet.size());
//        this.session.getAsyncRemote().sendText("恭喜:"+" 成功连接上WebSocket(其频道号："+session.getId()+")-->当前在线人数为："+webSocketSet.size());
    }

    @OnClose
    public void onClose(Session session) {
        List<String> stringList = this.session.getRequestParameterMap().get("userid");
        for (String string:
                stringList) {
            map.remove(string);
        }
        webSocketSet.remove(this);

        log.info("客户端：{}连接断开",session.getId());

        System.out.println("有一连接关闭！当前在线人数为" + webSocketSet.size());

    }

    @OnMessage
    public void onMsg(@PathParam("userid")String userid, String message,Session session) {
        Session userSession = map.get(userid);
        String fromUserID = stringRedisTemplate.opsForValue().get(userid);
        if(StringUtils.isNotBlank(fromUserID)){
            String id = IdUtil.objectId();
            String messageid = IdUtil.objectId();
            tbMessagerelationVo.setId(id);
            tbMessagerelationVo.setMessageid(messageid);
            tbMessagerelationVo.setFromuserid(userid);
            tbMessagerelationVo.setTouserid(fromUserID);
            tbMessagerelationVo.setMessage(message);
            tbMessagerelationVo.setIsdelete(0);
            tbMessagerelationVo.setCreatetime(LocalDateTime.now());
            BeanUtils.copyProperties(tbMessagerelationVo, tbMessagerelation);

            tbMessage.setId(IdUtil.objectId());
            tbMessage.setMessage(message);
            tbMessage.setMessageid(messageid);
            tbMessage.setIsdelete(0);
            if (map.containsKey(fromUserID)) {
                Session FromUserSession = map.get(fromUserID);

                FromUserSession.getAsyncRemote().sendText(JSON.toJSONString(tbMessagerelationVo));
                userSession.getAsyncRemote().sendText(JSON.toJSONString(tbMessagerelationVo));

                saveMessage(tbMessagerelation, tbMessage);
//        }
//        log.info("从客户端：{} 收到<--:{}", session.getId(),message);
//        String send=message.toUpperCase();
//        String result="客户：%s您好，来自server 的消息:%s";
//        result = String.format(result, session.getId(), send);
//        broadcast("来自server 的消息：" + result);
            }else {
                userSession.getAsyncRemote().sendText(JSON.toJSONString(tbMessagerelationVo));

                saveMessage(tbMessagerelation, tbMessage);
            }
        }else {
            userSession.getAsyncRemote().sendText("没有选择聊天的对象");
        }
    }

    private void saveMessage(TbMessagerelation tbMessagerelation, TbMessage tbMessage) {
        tbMessageMapper.insert(tbMessage);
        tbMessagerelationMapper.insert(tbMessagerelation);
    }

    /**
     * 群发自定义消息
     */
    public void broadcast(String message) {
        for (WebSocketService item : webSocketSet) {
            /**
             * 同步异步说明参考：http://blog.csdn.net/who_is_xiaoming/article/details/53287691
             *
             * this.session.getBasicRemote().sendText(message);
             **/
            item.session.getAsyncRemote().sendText(message);
        }
    }

}
